package top.v5it.japi.plus.log;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.servlet.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import top.v5it.japi.plus.common.context.Authorized;
import top.v5it.japi.plus.common.context.AuthorizedContextHolder;
import top.v5it.japi.plus.common.util.AddressUtil;

import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Objects;
import java.util.Optional;

import static cn.hutool.http.Header.AUTHORIZATION;

/**
 * 操作日志util
 *
 * @author zhanpu
 * @date 2020/3/18
 */
@Slf4j
public class OperLogUtil {

    private OperLogUtil() {
        throw new UnsupportedOperationException();
    }

    /**
     * 构造业务日志
     *
     * @param message 描述
     * @return {@link OperLog}
     */
    public static OperLog builder(final String message) {
        HttpServletRequest request = ((ServletRequestAttributes) Objects
                .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();

        return builder(request)
                .setMessage(message)
                .setType(OperType.BIZ)
                .setStatus(StrUtil.isNotBlank(message) ? 500 : 200);
    }

    /**
     * 构造身份认证日志
     *
     * @param request {@link HttpServletRequest}
     * @param time    方法执行时间
     * @param status  状态
     * @param message 描述
     * @return {@link OperLog}
     */
    public static OperLog builder(HttpServletRequest request, final long time, final int status, final String message) {

        return builder(request)
                .setTitle("权限认证")
                .setExecuteTime(time)
                .setMessage(message)
                .setType(OperType.AUTH)
                .setStatus(status);
    }

    /**
     * 构造操作日志
     *
     * @param request {@link HttpServletRequest}
     * @return {@link OperLog}
     */
    private static OperLog builder(HttpServletRequest request) {

        // 修复当关闭验证时，空指针异常
        Authorized authorized = Optional
                .ofNullable(AuthorizedContextHolder.getRequestAuthAttributes())
                .orElseGet(Authorized::new);

        String ip = ServletUtil.getClientIP(request);
        String authorization = request.getHeader(AUTHORIZATION.getValue());

        return new OperLog()
                .setGlobalTime(Instant.now().toEpochMilli() - authorized.getStartTime())
                .setChannel(authorized.getChannel())
                .setRequestId(authorized.getRequestId())
                .setMethod(request.getMethod())
                .setUserAgent(request.getHeader("user-agent"))
                .setOperUrl(URLUtil.getPath(request.getRequestURI()))
                .setOperIp(ip)
                .setOperAddr(AddressUtil.getCityInfo(ip))
                .setAuthorization(authorization)
                .setOperTime(LocalDateTime.now(ZoneId.systemDefault()));
    }

}
